/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1993 - 2000  Microsoft Corporation.  All Rights Reserved.

MODULE:     Property.c

PURPOSE:    Source module for the PROPERTY sample application

PLATFORMS:  Windows 95, Windows NT

FUNCTIONS:
WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
InitApplication(HINSTANCE);
InitInstance(HINSTANCE, int);
MainWndProc(HWND, UINT, WPARAM, LPARAM);
About(HWND, UINT, WPARAM, LPARAM);
DoModalPropSheet(HWND);
DoModelessPropSheet(HWND);
DoWizardPropSheet(HWND);
ButtonsDlgProc(HWND, UINT, WPARAM, LPARAM);
ComboDlgProc(HWND, UINT, WPARAM, LPARAM);
PropSheetCallback(HWND, UINT, LPARAM);

COMMENTS:

**************************************************************************/

#define STRICT

/**************************************************************************
Include Files
**************************************************************************/

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "property.h"
#pragma comment(lib, "comctl32.lib")	

/**************************************************************************
Local Function Prototypes
**************************************************************************/

int PASCAL       WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
BOOL             InitApplication(HINSTANCE);
BOOL             InitInstance(HINSTANCE, int);
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
INT_PTR          DoModalPropSheet(HWND);
HWND             DoModelessPropSheet(HWND);
INT_PTR          DoWizardPropSheet(HWND);
LRESULT CALLBACK ButtonsDlgProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ComboDlgProc(HWND, UINT, WPARAM, LPARAM);
void CALLBACK    PropSheetCallback(HWND, UINT, LPARAM);

/**************************************************************************
Global Variables
**************************************************************************/

HINSTANCE   g_hInst;
HWND        g_hwndPropSheet,
g_hwndMain;
BOOL        g_bWin95;
TCHAR       g_szClassName[] = TEXT("PropSheetClass");

/**************************************************************************

WinMain()

**************************************************************************/

int PASCAL WinMain(  HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nCmdShow)
{
	MSG      msg;

	g_hInst = hInstance;

	//don't forget this
	InitCommonControls();

	if(!hPrevInstance)
		if(!InitApplication(hInstance))
			return FALSE;

	if (!InitInstance(hInstance, nCmdShow))
		return FALSE;

	while(GetMessage(&msg, NULL, 0x00, 0x00))
	{
		// If the modeless guy is up and is ready to be destroyed
		// (PropSheet_GetCurrentPageHwnd returns NULL) then destroy the dialog.

		// PropSheet_GetCurrentPageHwnd will return NULL after the OK or Cancel 
		// button has been pressed and all of the pages have been notified. The 
		// Apply button doesn't cause this to happen.
		if(g_hwndPropSheet && (NULL == PropSheet_GetCurrentPageHwnd(g_hwndPropSheet)))
		{
			//enable the parent first to prevent another window from becoming the foreground window
			EnableWindow(g_hwndMain, TRUE);
			DestroyWindow(g_hwndPropSheet);
			g_hwndPropSheet = NULL;
		}

		//use PropSheet_IsDialogMessage instead of IsDialogMessage
		if(!PropSheet_IsDialogMessage(g_hwndPropSheet, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}

/**************************************************************************

InitApplication()

**************************************************************************/

BOOL InitApplication(HINSTANCE hInstance)
{
	OSVERSIONINFO  os;

	ZeroMemory(&os, sizeof(os));
	os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&os);
	if(os.dwMajorVersion >= 4)
		g_bWin95 = TRUE;
	else
		g_bWin95 = FALSE;

	if(g_bWin95)
	{
		WNDCLASSEX  wcex;

		ZeroMemory(&wcex, sizeof(wcex));

		wcex.cbSize          = sizeof(wcex);
		wcex.style           = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc     = (WNDPROC)MainWndProc;
		wcex.cbClsExtra      = 0;
		wcex.cbWndExtra      = 0;
		wcex.hInstance       = hInstance;
		wcex.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
		wcex.hCursor         = LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground   = GetStockObject(WHITE_BRUSH);
		wcex.lpszMenuName    = MAKEINTRESOURCE(IDR_MAIN_MENU);
		wcex.lpszClassName   = g_szClassName;

		return RegisterClassEx(&wcex);
	}
	else
	{
		WNDCLASS  wc;

		ZeroMemory(&wc, sizeof(wc));

		wc.style          = CS_HREDRAW | CS_VREDRAW;
		wc.lpfnWndProc    = (WNDPROC)MainWndProc;
		wc.cbClsExtra     = 0;
		wc.cbWndExtra     = 0;
		wc.hInstance      = hInstance;
		wc.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
		wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground  = GetStockObject(WHITE_BRUSH);
		wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MAIN_MENU);
		wc.lpszClassName  = g_szClassName;

		return RegisterClass(&wc);
	}
}

/**************************************************************************

InitInstance()

**************************************************************************/

BOOL InitInstance(   HINSTANCE hInstance,
				  int nCmdShow)
{
	g_hwndMain = CreateWindowEx(  0,
		g_szClassName,
		TEXT("Property Sheet Application"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

	if (!g_hwndMain)
	{
		return FALSE;
	}

	ShowWindow(g_hwndMain, nCmdShow);
	UpdateWindow(g_hwndMain);

	return TRUE;
}

/**************************************************************************

MainWndProc()

**************************************************************************/

LRESULT CALLBACK MainWndProc( HWND hWnd,
							 UINT uMessage,
							 WPARAM wParam,
							 LPARAM lParam)
{
	switch (uMessage)
	{
	case WM_CREATE:
		break;

	case WM_CLOSE:
		if(IsWindow(g_hwndPropSheet))
			DestroyWindow(g_hwndPropSheet);

		DestroyWindow(hWnd);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_COMMAND:
		switch (GET_WM_COMMAND_ID(wParam, lParam))
		{
		case IDM_MODAL:
			DoModalPropSheet(hWnd);
			break;

		case IDM_MODELESS:
			g_hwndPropSheet = DoModelessPropSheet(hWnd);
			break;

		case IDM_WIZARD:
			DoWizardPropSheet(hWnd);
			break;

		case IDM_EXIT:
			PostMessage(hWnd, WM_CLOSE, 0, 0);
			break;

		case IDM_ABOUT:
			DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), hWnd, About);
			break;
		}
		return TRUE;

	default:
		break;
	}
	return DefWindowProc(hWnd, uMessage, wParam, lParam);
}

/**************************************************************************

About()

**************************************************************************/

INT_PTR CALLBACK About( HWND hWnd, 
					   UINT uMessage, 
					   WPARAM wParam, 
					   LPARAM lParam)
{
	switch (uMessage)
	{
	case WM_INITDIALOG:
		return TRUE;

	case WM_COMMAND:
		switch(wParam)
		{
		case IDOK:
			EndDialog(hWnd, IDOK);
			return TRUE;

		case IDCANCEL:
			EndDialog(hWnd, IDCANCEL);
			return TRUE;
		}
		break;
	} 

	return FALSE;
}

/**************************************************************************

DoModalPropSheet()

**************************************************************************/

INT_PTR DoModalPropSheet(HWND hwndOwner)
{
	PROPSHEETPAGE psp[2];
	PROPSHEETHEADER psh;

	//Fill out the PROPSHEETPAGE data structure for the Background Color sheet
	psp[0].dwSize        = sizeof(PROPSHEETPAGE);
	psp[0].dwFlags       = PSP_USETITLE;
	psp[0].hInstance     = g_hInst;
	psp[0].pszTemplate   = MAKEINTRESOURCE(IDD_BUTTONS);
	psp[0].pszIcon       = NULL;
	psp[0].pfnDlgProc    = ButtonsDlgProc;
	psp[0].pszTitle      = TEXT("Buttons");
	psp[0].lParam        = 0;

	//Fill out the PROPSHEETPAGE data structure for the Client Area Shape sheet
	psp[1].dwSize        = sizeof(PROPSHEETPAGE);
	psp[1].dwFlags       = PSP_USETITLE;
	psp[1].hInstance     = g_hInst;
	psp[1].pszTemplate   = MAKEINTRESOURCE(IDD_COMBOBOXES);
	psp[1].pszIcon       = NULL;
	psp[1].pfnDlgProc    = ComboDlgProc;
	psp[1].pszTitle      = TEXT("Combo Boxes");
	psp[1].lParam        = 0;

	//Fill out the PROPSHEETHEADER
	psh.dwSize           = sizeof(PROPSHEETHEADER);
	psh.dwFlags          = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
	psh.hwndParent       = hwndOwner;
	psh.hInstance        = g_hInst;
	psh.pszIcon          = MAKEINTRESOURCE(IDI_BACKCOLOR);
	psh.pszCaption       = TEXT("Modal Property Sheet");
	psh.nPages           = sizeof(psp) / sizeof(PROPSHEETPAGE);
	psh.ppsp             = (LPCPROPSHEETPAGE) &psp;
	psh.pfnCallback      = (PFNPROPSHEETCALLBACK)PropSheetCallback;

	//And finally display the modal property sheet
	return PropertySheet(&psh);
}

/**************************************************************************

DoModelessPropSheet()

**************************************************************************/

HWND DoModelessPropSheet(HWND hwndOwner)
{
	PROPSHEETPAGE psp[2];
	PROPSHEETHEADER psh;

	//Fill out the PROPSHEETPAGE data structure for the Background Color sheet
	psp[0].dwSize        = sizeof(PROPSHEETPAGE);
	psp[0].dwFlags       = PSP_USETITLE;
	psp[0].hInstance     = g_hInst;
	psp[0].pszTemplate   = MAKEINTRESOURCE(IDD_BUTTONS);
	psp[0].pszIcon       = NULL;
	psp[0].pfnDlgProc    = ButtonsDlgProc;
	psp[0].pszTitle      = TEXT("Buttons");
	psp[0].lParam        = 0;

	//Fill out the PROPSHEETPAGE data structure for the Client Area Shape sheet
	psp[1].dwSize        = sizeof(PROPSHEETPAGE);
	psp[1].dwFlags       = PSP_USETITLE;
	psp[1].hInstance     = g_hInst;
	psp[1].pszTemplate   = MAKEINTRESOURCE(IDD_COMBOBOXES);
	psp[1].pszIcon       = NULL;
	psp[1].pfnDlgProc    = ComboDlgProc;
	psp[1].pszTitle      = TEXT("Combo Boxes");
	psp[1].lParam        = 0;

	//Fill out the PROPSHEETHEADER
	psh.dwSize           = sizeof(PROPSHEETHEADER);
	psh.dwFlags          = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK| PSH_MODELESS;
	psh.hwndParent       = hwndOwner;
	psh.hInstance        = g_hInst;
	psh.pszIcon          = MAKEINTRESOURCE(IDI_BACKCOLOR);
	psh.pszCaption       = TEXT("Modeless Property Sheet");
	psh.nPages           = sizeof(psp) / sizeof(PROPSHEETPAGE);
	psh.ppsp             = (LPCPROPSHEETPAGE) &psp;
	psh.pfnCallback      = (PFNPROPSHEETCALLBACK)PropSheetCallback;

	//disable the parent to prevent another property sheet from being created - this will be re-enabled when the property sheet is destroyed.
	EnableWindow(hwndOwner, FALSE);

	//And finally display the modeless property sheet. It will be destroyed in our main message loop.
	return (HWND)PropertySheet(&psh);
}

/**************************************************************************

DoWizardPropSheet()

**************************************************************************/

INT_PTR DoWizardPropSheet(HWND hwndOwner)
{
	PROPSHEETPAGE psp[2];
	PROPSHEETHEADER psh;

	//Fill out the PROPSHEETPAGE data structure for the Background Color sheet
	psp[0].dwSize        = sizeof(PROPSHEETPAGE);
	psp[0].dwFlags       = PSP_USETITLE;
	psp[0].hInstance     = g_hInst;
	psp[0].pszTemplate   = MAKEINTRESOURCE(IDD_BUTTONS);
	psp[0].pszIcon       = NULL;
	psp[0].pfnDlgProc    = ButtonsDlgProc;
	psp[0].pszTitle      = TEXT("Buttons");
	psp[0].lParam        = 0;

	//Fill out the PROPSHEETPAGE data structure for the Client Area Shape sheet
	psp[1].dwSize        = sizeof(PROPSHEETPAGE);
	psp[1].dwFlags       = PSP_USETITLE;
	psp[1].hInstance     = g_hInst;
	psp[1].pszTemplate   = MAKEINTRESOURCE(IDD_COMBOBOXES);
	psp[1].pszIcon       = NULL;
	psp[1].pfnDlgProc    = ComboDlgProc;
	psp[1].pszTitle      = TEXT("Combo Boxes");
	psp[1].lParam        = 0;

	//Fill out the PROPSHEETHEADER
	psh.dwSize           = sizeof(PROPSHEETHEADER);
	psh.dwFlags          = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_USEICONID | PSH_USECALLBACK;
	psh.hwndParent       = hwndOwner;
	psh.hInstance        = g_hInst;
	psh.pszIcon          = MAKEINTRESOURCE(IDI_BACKCOLOR);
	psh.pszCaption       = TEXT("Wizard Property Sheet");
	psh.nPages           = sizeof(psp) / sizeof(PROPSHEETPAGE);
	psh.ppsp             = (LPCPROPSHEETPAGE) &psp;
	psh.pfnCallback      = (PFNPROPSHEETCALLBACK)PropSheetCallback;

	//And finally display the Wizard property sheet
	return PropertySheet(&psh);
}

/**************************************************************************

ButtonsDlgProc()

**************************************************************************/

LRESULT CALLBACK ButtonsDlgProc( HWND hdlg,
								UINT uMessage,
								WPARAM wParam,
								LPARAM lParam)
{
	LPNMHDR     lpnmhdr;

	switch (uMessage)
	{
		// on any command notification, tell the property sheet to enable the Apply button
	case WM_COMMAND:
		PropSheet_Changed(GetParent(hdlg), hdlg);
		break;

	case WM_NOTIFY:
		lpnmhdr = (NMHDR FAR *)lParam;

		switch (lpnmhdr->code)
		{
		case PSN_APPLY:   //sent when OK or Apply button pressed
			break;

		case PSN_RESET:   //sent when Cancel button pressed
			break;

		case PSN_SETACTIVE:
			//this will be ignored if the property sheet is not a wizard
			PropSheet_SetWizButtons(GetParent(hdlg), PSWIZB_NEXT);
			break;

		default:
			break;
		}
		break;

	default:
		break;
	}

	return FALSE;
}

/**************************************************************************

ComboDlgProc()

**************************************************************************/

LRESULT CALLBACK ComboDlgProc(   HWND hdlg,
							  UINT uMessage,
							  WPARAM wParam,
							  LPARAM lParam)
{
	LPNMHDR     lpnmhdr;

	switch (uMessage)
	{
		// on any command notification, tell the property sheet to enable the Apply button
	case WM_COMMAND:
		PropSheet_Changed(GetParent(hdlg), hdlg);
		break;

	case WM_NOTIFY:
		lpnmhdr = (NMHDR FAR *)lParam;

		switch (lpnmhdr->code)
		{
		case PSN_APPLY:   //sent when OK or Apply button pressed
			break;

		case PSN_RESET:   //sent when Cancel button pressed
			break;

		case PSN_SETACTIVE:
			//this will be ignored if the property sheet is not a wizard
			PropSheet_SetWizButtons(GetParent(hdlg), PSWIZB_BACK | PSWIZB_FINISH);
			return FALSE;

		default:
			break;
		}
		break;

	default:
		break;
	}

	return FALSE;
}

/**************************************************************************

PropSheetCallback()

**************************************************************************/

void CALLBACK PropSheetCallback(HWND hwndPropSheet, UINT uMsg, LPARAM lParam)
{
	switch(uMsg)
	{
		//called before the dialog is created, hwndPropSheet = NULL, lParam points to dialog resource
	case PSCB_PRECREATE:
		{
			LPDLGTEMPLATE  lpTemplate = (LPDLGTEMPLATE)lParam;

			if(!(lpTemplate->style & WS_SYSMENU))
			{
				lpTemplate->style |= WS_SYSMENU;
			}
		}
		break;

		//called after the dialog is created
	case PSCB_INITIALIZED:
		break;

	}
}
